package com.tony.business.config;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * @author x
 */
@Configuration
public class JsonConfig {

    private BeanSerializerModifier beanSerializerModifier = new BeanSerializerModifier() {
        private JsonSerializer<Object> nullArray = new JsonSerializer<Object>() {
            @Override
            public void serialize(Object value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                if (value == null) {
                    jsonGenerator.writeStartArray();
                    jsonGenerator.writeEndArray();
                }else{
                    jsonGenerator.writeObject(value);
                }
            }
        };

        private JsonSerializer<Object> nullStr = new JsonSerializer<Object>() {
            @Override
            public void serialize(Object value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                if(value==null) {
                    jsonGenerator.writeString("");
                }else{
                    jsonGenerator.writeObject(value);
                }
            }
        };

        private JsonSerializer<Object> nullNumber = new JsonSerializer<Object>() {
            @Override
            public void serialize(Object value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                if(value==null){
                    jsonGenerator.writeObject(0);
                }else{
                    jsonGenerator.writeObject(value);
                }
            }
        };

        @Override
        public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
            //循环所有的beanPropertyWriter
            for (BeanPropertyWriter writer : beanProperties) {
                JavaType javaType = writer.getType();
                Class<?> clazz = javaType.getRawClass();
                //判断字段是Array类型
                if (clazz.isArray() || clazz.equals(List.class) || clazz.equals(Set.class)) {
                    //给writer注册一个自己的nullSerializer
                    writer.assignNullSerializer(nullArray);
                    //判断字段是字符串类型
                } else if (clazz.equals(String.class)) {
                    writer.assignNullSerializer(nullStr);
                    //判断字段是数值类型
                } else if (clazz.equals(Integer.class)||clazz.equals(Long.class)||clazz.equals(BigDecimal.class)) {
                    writer.assignNullSerializer(nullNumber);
                    //判断字段是日期类型
                } else if (clazz.equals(Date.class)) {
                    writer.assignNullSerializer(nullStr);
                    //判断字段是日期类型
                } else if (clazz.equals(LocalDateTime.class) || clazz.equals(LocalDate.class) || clazz.equals(LocalTime.class)){
                    writer.assignNullSerializer(nullStr);
                }
            }
            return beanProperties;
        }

    };

    /**
     * 把null改为0,"",[]等
     */
    /*@Bean
    public ObjectMapper setBeanSerializerModifier(Jackson2ObjectMapperBuilder builder){
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
        objectMapper.setSerializerFactory(objectMapper.getSerializerFactory().withSerializerModifier(beanSerializerModifier));
        return objectMapper;
    }*/

    /**
     * Date格式化字符串
     */
    private static final String DATE_FORMAT = "yyyy-MM-dd";
    /**
     * DateTime格式化字符串
     */
    private static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    /**
     * Time格式化字符串
     */
    private static final String TIME_FORMAT = "HH:mm:ss";

    /**
     * 自定义Bean
     */
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
        return builder -> builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATETIME_FORMAT)))
                .serializerByType(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DATE_FORMAT)))
                .serializerByType(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(TIME_FORMAT)))
                .deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DATETIME_FORMAT)))
                .deserializerByType(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DATE_FORMAT)))
                .deserializerByType(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(TIME_FORMAT)))

                //解析枚举类型
                .featuresToEnable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
    }

}
